package ioimpl

import (
	"bytes"
	"github.com/pkg/errors"
	"io"
	"os"
	"yizhuoyan/go-study/pdfgo/characterset"
	"yizhuoyan/go-study/pdfgo/handyio"
)

type PdfRawReaderFromFile struct {
	file         *os.File
	currentIndex int64 `#:"当前下标"`
	maxIndex     int64 `#:"最大下标"`
}

func NewPdfRawReaderFromFile(file *os.File) (*PdfRawReaderFromFile, error) {
	endIndex, err := file.Seek(0, io.SeekEnd)
	if err != nil {
		return nil, err
	}
	return &PdfRawReaderFromFile{
		file:         file,
		currentIndex: endIndex,
		maxIndex:     endIndex,
	}, nil
}

func (this *PdfRawReaderFromFile) NextByte() (byte, error) {
	var oneByte = []byte{0}

	readed, err := this.file.Read(oneByte)
	if readed > 0 {
		this.currentIndex++
		return oneByte[0], nil
	}
	return 0, err

}

func (this *PdfRawReaderFromFile) NextByteEquals(b byte) bool {
	nextByte, err := this.NextByte()
	if err != nil {
		return false
	}
	if nextByte == b {
		return true
	}
	//backward if is not
	_ = this.indexOffset(-1)
	return false
}

func (this *PdfRawReaderFromFile) NextBytesEquals(bs []byte) bool {
	oldCurrentIndex := this.IndexCurrent()
	for _, b := range bs {
		nextByte, err := this.NextByte()
		if err != nil {
			_ = this.IndexMoveTo(oldCurrentIndex)
			return false
		}
		if nextByte != b {
			_ = this.IndexMoveTo(oldCurrentIndex)
			return false
		}
	}
	return true
}

func (this *PdfRawReaderFromFile) NextBytes(f func(byte) int) []byte {
	var rst = new(bytes.Buffer)
	loop := true
	for loop {
		nextByte, err := this.NextByte()
		if err != nil {
			loop = false
			break
		}
		switch f(nextByte) {
		case handyio.ReadNext:
			rst.WriteByte(nextByte)
		case handyio.ReadByteSkip:
			continue
		case handyio.ReadStop:
			_ = this.indexOffset(-1)
			loop = false
			break
		}
	}
	return rst.Bytes()
}

func (this *PdfRawReaderFromFile) NextBytesUntilWhiteSpace() []byte {
	var rst = new(bytes.Buffer)
	for true {
		nextByte, err := this.NextByte()
		if err != nil {
			break
		}
		if characterset.IsWhiteSpaceChar(nextByte) {
			_ = this.indexOffset(-1)
			break
		}
		rst.WriteByte(nextByte)
	}
	return rst.Bytes()

}

func (this *PdfRawReaderFromFile) SkipNextWhiteSpaces() {
	for true {
		nextByte, err := this.NextByte()
		if err != nil {
			break
		}
		if !characterset.IsWhiteSpaceChar(nextByte) {
			_ = this.indexOffset(-1)
			return
		}
	}
}
func (this *PdfRawReaderFromFile) SkipNextEndOfLine() {
	for true {
		nextByte, err := this.NextByte()
		if err != nil {
			break
		}
		if !characterset.IsEndOfLineChar(nextByte) {
			_ = this.indexOffset(-1)
			return
		}
	}
}

func (this *PdfRawReaderFromFile) IndexCurrent() int64 {
	return this.currentIndex
}

func (this *PdfRawReaderFromFile) IndexEnd() int64 {
	return this.maxIndex
}
func (this *PdfRawReaderFromFile) indexOffset(i int64) error {
	seek, err := this.file.Seek(i, io.SeekCurrent)
	if err != nil {
		return err
	}
	this.currentIndex = seek
	return nil
}
func (this *PdfRawReaderFromFile) IndexMoveTo(i int64) error {
	if i == this.currentIndex {
		return nil
	}
	if i < 0 {
		return errors.New("下标不能小于0")
	}
	if i > this.maxIndex {
		return errors.New("下标超出范围")
	}
	seek, err := this.file.Seek(i, io.SeekStart)
	if err != nil {
		return err
	}
	this.currentIndex = seek
	return nil
}

func (this *PdfRawReaderFromFile) NotSupport(message string) error {
	return &NotSupportError{message: message}
}

func (this *PdfRawReaderFromFile) IsNotSupportError(err error) bool {
	if _, has := err.(*NotSupportError); has {
		return true
	}
	return false
}
